package bakaserver.cdkeysystem;

import net.milkbowl.vault.economy.Economy;

import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.*;
import java.util.logging.Logger;

public final class cdkeysystem extends JavaPlugin {
	public Logger consoleLogger = getLogger();
	public String driver;
	public String url;
	public String user;
	public String password;
	public Connection conn;
	public Statement statement;
	public String table;
	public YamlConfiguration yamlConfig;
	public File cfg;
	public Economy econ;
	public boolean vault;
	public ItemStack itemstack;

	boolean hasVault() {
		if (getServer().getPluginManager().getPlugin("Vault") == null) {
			return false;
		}
		RegisteredServiceProvider<Economy> rsp = getServer()
				.getServicesManager().getRegistration(Economy.class);
		if (rsp == null) {
			return false;
		}
		econ = rsp.getProvider();
		return econ != null;

	}

	boolean hasEcon() {
		return (getServer().getServicesManager().getRegistration(Economy.class)) != null;
	}

	void OutputExcpetion(Exception e) {
		getLogger().info("->" + e.getMessage());
		getLogger().info("->" + e.toString());
		getLogger().info("->" + e.getLocalizedMessage());
	}

	void ExecuteSQLUpdate(String SQLCommand) throws SQLException {
		statement.close();
		conn.close();
		conn = DriverManager.getConnection(url, user, password);
		statement = conn.createStatement();
		consoleLogger.info(SQLCommand);
		statement.executeUpdate(SQLCommand);
	}

	ResultSet ExecuteSQLQuery(String SQLCommand) throws SQLException {
		statement.close();
		conn.close();
		conn = DriverManager.getConnection(url, user, password);
		statement = conn.createStatement();
		consoleLogger.info(SQLCommand);
		return statement.executeQuery(SQLCommand);
	}

	boolean CreateConfig() {
		try {
			InputStream in = getResource("config.yml");
			OutputStream out = new FileOutputStream(cfg);

			byte[] buffer = new byte[1024];
			int len;
			while ((len = in.read(buffer)) != -1) {
				out.write(buffer, 0, len);
			}

			in.close();
			out.close();
		} catch (Exception e) {
			this.consoleLogger.info("Can't create config.yml file.");
			return false;
		}
		return true;
	}

	boolean LoadConfig() {
		yamlConfig = new YamlConfiguration();
		try {
			yamlConfig.load(cfg);
			this.driver = yamlConfig.getString("sqlConfig.driver");
			this.url = yamlConfig.getString("sqlConfig.url");
			this.user = yamlConfig.getString("sqlConfig.user");
			this.password = yamlConfig.getString("sqlConfig.password");
			this.table = yamlConfig.getString("sqlConfig.table");
		} catch (FileNotFoundException e) {
			this.consoleLogger.info("Config file not found , plugin disabled");
			this.setEnabled(false);
			return false;
		} catch (IOException e) {
			e.printStackTrace();
			this.consoleLogger
					.info("IO Exception catched , please check your harddisk");
			return false;
		} catch (InvalidConfigurationException e) {
			e.printStackTrace();
			this.consoleLogger
					.info("Config invalid! Check your config and reload plugin");
			return false;
		}
		return true;
	}

	boolean Reload(CommandSender sender) {
		if (!sender.hasPermission("cdk.reload")) {
			sender.sendMessage("权限不足");
			consoleLogger.info("Player tried reload plugin!");
			return false;
		} else {
			try {
				this.statement.close();
				this.conn.close();
			} catch (SQLException e) {
				this.consoleLogger.info("Error reloading");
				return false;
			}
			this.LoadConfig();
			consoleLogger.info("Reload successful.");
			return true;
		}
	}

	boolean ShowHelp(CommandSender sender) {

		if (sender instanceof Player) {
			sender.sendMessage("BAKA Server cdKey system");
			if (sender.hasPermission("cdk.activeCDKEY"))
				sender.sendMessage("/cdkey active [your cdkey] - avtive a cdkey");
			if (sender.hasPermission("cdk.createCDKEY"))
				sender.sendMessage("/cdkey create [cdkey] [valid] [max] [value] [LimitUser1;LimitUser2;...] [gold] [item]");
			if (sender.hasPermission("cdk.reload"))
				sender.sendMessage("/cdkey reload - reload config");
			if (sender.hasPermission("cdk.updateCDKEY"))
				sender.sendMessage("/cdkey update [need update cdkey] [valid] [max] [value] [LimitUser1;LimitUser2;...] [gold] [item]");
			if (sender.hasPermission("cdk.deleteCDKEY"))
				sender.sendMessage("/cdkey delete [need delete cdkey]");
			return true;
		}
		return false;
	}

	@SuppressWarnings("deprecation")
	boolean ActiveCDKEY(CommandSender sender, String cdkey) {
		if (!sender.hasPermission("cdk.activeCDKEY"))
			return this.ExceptionErrorPerm(sender, "active cdkey " + cdkey);

		try {
			ResultSet rs = ExecuteSQLQuery("select * from " + table
					+ " where ikey='" + cdkey + "'");
			if (!rs.first())
				return this.ExcpetionErrorCDKEYExist(sender);
			int value = rs.getInt("value");
			int max = rs.getInt("max");
			String user = rs.getString("users");
			String item = rs.getString("item");
			int gold = rs.getInt("gold");
			if (rs.getInt("valid") == 1) {
				if (max > value || rs.getInt("max") == -1) {
					if (!user.contains(";" + sender.getName())) {
						ExecuteSQLUpdate("update " + table + " set value="
								+ (value + 1) + " where ikey='" + cdkey + "'");
						ExecuteSQLUpdate("update " + table + " set users='"
								+ user + ";" + sender.getName()
								+ "' where ikey='" + cdkey + "'");
						for (String k : item.split(";")) {
							String[] h = k.split(":");
							itemstack = new ItemStack(Integer.parseInt(h[0]),
									Integer.parseInt(h[1]));
							((Player) sender).getInventory().addItem(itemstack);
						}
						if (vault)
							econ.depositPlayer(sender.getName(), gold);
						for (Player player : getServer().getOnlinePlayers()) {
							if (player != sender)
								player.sendMessage("玩家" + sender.getName()
										+ "兑换了cdKey，得到了" + String.valueOf(gold)
										+ econ.currencyNamePlural());
						}
						if (value >= max)
							ExecuteSQLUpdate("update " + table
									+ " set valid=0 where ikey='" + cdkey + "'");
						sender.sendMessage("成功兑换CDKEY:" + cdkey);
						statement.close();
						conn.close();

					} else {
						sender.sendMessage("一个人只能激活一次哦~");
						statement.close();
						conn.close();
					}
				} else {
					sender.sendMessage("这个CDKEY激活次数已经用尽.");
					statement.close();
					conn.close();
				}
			} else {
				consoleLogger.info("Player" + sender.getName()
						+ "try active a disvailed cdkey:" + cdkey);
				sender.sendMessage("你输入的CDKEY已经失效.");
				statement.close();
				conn.close();
			}

		} catch (SQLException e) {
			OutputExcpetion(e);
			sender.sendMessage("A Database error exception while loading cdkey-data");
			return false;
		} catch (Exception e) {
			OutputExcpetion(e);
			sender.sendMessage("A error exception while loading cdkey-data");
			return false;

		}

		return true;
	}

	boolean CreateCDKEY(CommandSender sender, String cdkey, String valid,
			String max, String value, String limitUsers, String gold,
			String items) {
		if (!sender.hasPermission("cdk.createCDKEY"))
			return ExceptionErrorPerm(sender, "create cdkey" + cdkey);
		try {
			if (ExecuteSQLQuery(
					"select * from " + table + " where ikey='" + cdkey + "'")
					.first()) {
				return ExcpetionErrorCDKEYExist(sender);
			} else {
				ExecuteSQLUpdate("insert into " + table
						+ " (ikey,valid,max,value,users,gold,item) values ('"
						+ cdkey + "','" + valid + "','" + max + "','" + value
						+ "','" + limitUsers + "','" + gold + "','" + items
						+ "')");
				sender.sendMessage("Create CDKEY successful.");
				return true;
			}
		} catch (SQLException e) {
			OutputExcpetion(e);
			return false;
		}

	}

	boolean DeleteCDKEY(CommandSender sender, String cdkey) {
		if (!sender.hasPermission("cdk.deleteCDKEY"))
			return this.ExceptionErrorPerm(sender, "delete cdkey" + cdkey);

		try {
			if (!ExecuteSQLQuery(
					"select * from " + table + " where ikey='" + cdkey + "'")
					.first()) {
				return this.ExcpetionErrorCDKEYExist(sender);
			} else {
				ExecuteSQLUpdate("delete from " + table + " where ikey='"
						+ cdkey + "'");
				sender.sendMessage("Deleted cdkey Successful.");
				return true;
			}
		} catch (SQLException e) {
			OutputExcpetion(e);
			this.consoleLogger.info("An error excpetion when deleting CDKEY");
			return false;
		}

	}

	boolean UpdateCDKEY(CommandSender sender, String cdkey, String valid,
			String max, String value, String limitUsers, String gold,
			String items) {
		if (!sender.hasPermission("cdk.updateCDKEY"))
			return ExceptionErrorPerm(sender, "update cdkey" + cdkey);

		try {
			if (!ExecuteSQLQuery(
					"select * from " + table + " where ikey='" + cdkey + "'")
					.first()) {
				return ExcpetionErrorCDKEYExist(sender);
			} else {
				ExecuteSQLUpdate("update " + table + " set valid=" + valid
						+ " where ikey='" + cdkey + "'");
				ExecuteSQLUpdate("update " + table + " set max=" + max
						+ " where ikey='" + cdkey + "'");
				ExecuteSQLUpdate("update " + table + " set value=" + value
						+ " where ikey='" + cdkey + "'");
				ExecuteSQLUpdate("update " + table + " set users='"
						+ limitUsers + "' where ikey='" + cdkey + "'");
				ExecuteSQLUpdate("update " + table + " set gold=" + gold
						+ " where ikey='" + cdkey + "'");
				ExecuteSQLUpdate("update " + table + " set item='" + items
						+ "' where ikey='" + cdkey + "'");
				sender.sendMessage("Update cdkey successful.");
				return true;
			}
		} catch (SQLException e) {
			OutputExcpetion(e);
			this.consoleLogger.info("An error excpetion when deleting CDKEY");
			return false;
		}
	}

	@Override
	public void onEnable() {
		if (!getDataFolder().exists()) {
			this.consoleLogger
					.info("Can't load config file ,please config the plugin after use it.");
			this.getDataFolder().mkdir();
			this.CreateConfig();
		}
		cfg = new File(this.getDataFolder(), "config.yml");
		if (!cfg.exists()) {
			this.CreateConfig();
			this.consoleLogger.info("Config loaded fail, copy form jar.");
			this.setEnabled(false);
		}
		if (this.cfg.exists())
			LoadConfig();

		try {
			Class.forName(driver);
			conn = DriverManager.getConnection(url, user, password);
			statement = conn.createStatement();
			DatabaseMetaData meta = conn.getMetaData();
			ResultSet rs = meta.getTables(null, null, table, null);
			if (!rs.next()) {
				consoleLogger.info("The table" + table
						+ " not exist in yoru database, auto created.");
				ExecuteSQLUpdate("create table " + table + "(ikey varchar(100) not null primary key ,valid int(1) not null ,max int(11) not null ,value int(11),users varchar(512),gold int(11),item varchar(100))");
			}
			rs.close();
			statement.close();
			conn.close();
		} catch (ClassNotFoundException e) {
			consoleLogger.info("数据库驱动加载失败 ");
			this.setEnabled(false);
			return;
		} catch (SQLException e) {
			consoleLogger.info("数据库连接失败");
			consoleLogger.info(e.getSQLState());
			consoleLogger.info(e.getMessage());
			consoleLogger.info(e.getLocalizedMessage());
			this.setEnabled(false);
			return;
		} catch (Exception e) {
			consoleLogger.info("未知错误");
			this.setEnabled(false);
			return;
		}
		if (hasVault()) {
			vault = true;
			econ = getServer().getServicesManager()
					.getRegistration(Economy.class).getProvider();
		} else {
			vault = false;
			econ = null;
		}

		consoleLogger.info("BAKAServer CDKEY System Started Successfuly!!");
	}

	@Override
	public void onDisable() {
		try {
			this.conn.close();
			this.statement.close();
		} catch (SQLException e) {
			this.consoleLogger
					.info("SQL Database disconnect error ,check your sql config correctly.");
		} catch (Exception e) {
			this.consoleLogger.info("Plugins disabled!.");
		}

		this.consoleLogger.info("BAKAServer CDKEY System Closed Successfully!");
	}

	boolean ExceptionErrorArgs(CommandSender sender) {
		sender.sendMessage("Args Error.");
		return false;
	}

	boolean ExceptionErrorPerm(CommandSender sender, String Action) {
		sender.sendMessage("Perm Error.");
		consoleLogger.info("Player" + sender.getName() + "tried try " + Action);
		return false;
	}

	boolean ExcpetionErrorCDKEYExist(CommandSender sender) {
		sender.sendMessage("CDKEY Error");
		consoleLogger.info("Player" + sender.getName()
				+ "tired try a non-exist cdkey");
		return false;
	}

	boolean ExcpetionErrorSender(CommandSender sender) {
		sender.sendMessage("This command must run in a player");
		return false;
	}

	@Override
	public boolean onCommand(CommandSender sender, Command cmd, String label,
			String[] args) {
		if (!(cmd.getName().equalsIgnoreCase("cdkey") && (sender instanceof Player))){
			ExcpetionErrorSender(sender);
			return false;
		}
		if (args.length < 1) {
			return ExceptionErrorArgs(sender);
		} else {
			if (args.length == 1) {
				switch (args[0].toLowerCase()) {
				case ("help"):
					return ShowHelp(sender);
				case ("?"):
					return ShowHelp(sender);
				case ("reload"):
					return Reload(sender);
				default:
					return true;
				}
			} else if (args.length == 2) {
				switch (args[0].toLowerCase()) {
				case ("active"):
					return this.ActiveCDKEY(sender, args[1]);
				case ("delete"):
					return this.DeleteCDKEY(sender, args[1]);
				default:
					return true;
				}
			} else if (args.length == 9 || args.length == 8) {
				switch (args[0].toLowerCase()) {
				case ("update"):
					return this.UpdateCDKEY(sender, args[1], args[2], args[3],
							args[4], args[5], args[6], args[7]);
				case ("create"):
					return this.CreateCDKEY(sender, args[1], args[2], args[3],
							args[4], args[5], args[6], args[7]);
				default:
					return true;
				}
			} else {
				return ExceptionErrorArgs(sender);
			}
		}
	}

}
